package cn.codingjc.framework.common.util.proxy.util;

import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;

import javax.annotation.Resource;
import javax.net.ssl.SSLContext;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * @Author: jj.xue
 * @createTime: 2023年06月16日 14:48:13
 * @Description:
 */
@Slf4j
public class HttpclientUtils {
    public static final String CONTENT_TYPE = "application/x-www-form-urlencoded";
    public static final String CONTENT_TYPE_JSON = "application/json";
    public static final String ssoProxyHost = "";
    public static final Integer ssoProxyPort = 0;
    public static final String ssoProxyUserName = "";
    public static final String ssoProxyPassword = "";

    public static String getResultByProxy(String url, String jsonBody, Map<String, String> headerMap) {
        String response = null;
        HttpPost httpPost = null;
        try {
            //设置请求配置类  重点就是在这里添加setProxy 设置代理
            HttpHost proxy = new HttpHost(ssoProxyHost, ssoProxyPort, "http");
            CredentialsProvider provider = new BasicCredentialsProvider();
            provider.setCredentials(new AuthScope(proxy), new UsernamePasswordCredentials(ssoProxyUserName, ssoProxyPassword));
            CloseableHttpClient httpClient = getHttpClient(url, provider);
            // CloseableHttpClient httpClient = HttpClients.custom().build();
            RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(15000).setConnectTimeout(15000)
                    .setConnectionRequestTimeout(15000).setProxy(proxy).build();
            httpPost = new HttpPost(url);
            httpPost.setConfig(requestConfig);
            log.info("header is:{}", headerMap);
            if (headerMap != null && headerMap.size() > 0) {
                for (Map.Entry<String, String> entry : headerMap.entrySet()) {
                    httpPost.addHeader(entry.getKey(), entry.getValue());
                }
            }
            httpPost.setEntity(new StringEntity(jsonBody, "UTF-8"));
            response = getHttpClientResponseByJson(httpPost, httpClient);
        } catch (Exception e) {
            log.info("HttpclientUtils 代理执行发生异常！", e);
        } finally {
            if (null != httpPost) {
                httpPost.releaseConnection();
            }
        }
        return response;
    }

    public static String getResultByProxy(String url,
                                          String proxyHost, int proxyPort,
                                          String proxyUserName, String proxyPassword,
                                          Map<String, String> paramsMap) {
        String response = null;
        HttpPost httpPost = null;
        try {

            //设置请求配置类  重点就是在这里添加setProxy 设置代理
            HttpHost proxy = new HttpHost(proxyHost, proxyPort, "http");
            CredentialsProvider provider = new BasicCredentialsProvider();
            provider.setCredentials(new AuthScope(proxy), new UsernamePasswordCredentials(proxyUserName, proxyPassword));
            CloseableHttpClient httpClient = getHttpClient(url, provider);
            // CloseableHttpClient httpClient = HttpClients.custom().build();
            RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(15000).setConnectTimeout(15000)
                    .setConnectionRequestTimeout(15000).setProxy(proxy).build();

            httpPost = new HttpPost(url);
            httpPost.setConfig(requestConfig);
            httpPost.addHeader("Content-Type", CONTENT_TYPE);
            List<NameValuePair> nameValuePairs = new ArrayList<>();
            if (paramsMap.size() != 0) {
                Set keySet = paramsMap.keySet();
                Iterator it = keySet.iterator();
                while (it.hasNext()) {
                    String k = it.next().toString();
                    String v = paramsMap.get(k);
                    nameValuePairs.add(new BasicNameValuePair(k, v));
                }
            }
            httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, "UTF-8"));


            response = getHttpClientResponse(httpPost, httpClient);
        } catch (Exception e) {
            log.info("HttpclientUtils 代理执行发生异常！", e);
        } finally {
            if (null != httpPost) {
                httpPost.releaseConnection();
            }
        }
        return response;
    }

    private static String getHttpClientResponse(HttpPost httpPost, HttpClient httpClient) throws Exception {
        log.info("HttpclientUtils 代理执行开始 httpPost={},httpClient={}", JSONUtil.toJsonStr(httpPost), JSONUtil.toJsonStr(httpClient));
        String result = null;
        HttpResponse httpResponse = httpClient.execute(httpPost);
        HttpEntity entity = httpResponse.getEntity();
        if (null != entity) {
            try (InputStream inputStream = entity.getContent()) {
                byte[] bytes = read(inputStream, 1024);
                result = new String(bytes, StandardCharsets.UTF_8);
            }
        }
        log.info("HttpclientUtils 代理执行完成 result={}", result);
        return result;
    }
    private static String getHttpClientResponseByJson(HttpPost httpPost, HttpClient httpClient) throws Exception {
        log.info("HttpclientUtils 代理执行开始 httpPost={},httpClient={}", JSONUtil.toJsonStr(httpPost), JSONUtil.toJsonStr(httpClient));
        HttpResponse httpResponse = httpClient.execute(httpPost);
        HttpEntity entity = httpResponse.getEntity();
        String result = EntityUtils.toString(entity, "UTF-8");
        log.info("HttpclientUtils 代理执行完成 result={}", result);
        return result;
    }

    private static CloseableHttpClient getHttpClient(String url, CredentialsProvider provider) throws Exception {
        CloseableHttpClient httpClient;
        String lowerURL = url.toLowerCase();
        if (lowerURL.startsWith("https")) {
            httpClient = createSSLClientDefault(provider);
        } else {
            httpClient = HttpClients.custom().setDefaultCredentialsProvider(provider).build();
        }
        return httpClient;
    }

    private static CloseableHttpClient createSSLClientDefault(CredentialsProvider provider) throws Exception {
        SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, (chain, authType) -> true).build();
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, (s, sslSession) -> true);
        return HttpClients.custom().setDefaultCredentialsProvider(provider).setSSLSocketFactory(sslsf).build();
    }

    public static byte[] read(InputStream inputStream, int bufferSize) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] buffer = new byte[bufferSize];

        for (int num = inputStream.read(buffer); num != -1; num = inputStream.read(buffer)) {
            baos.write(buffer, 0, num);
        }

        baos.flush();
        return baos.toByteArray();
    }
}
